//written by mark on 2013/9/21
//this program is to implement some way of a hashconsisting of adding,finding,deleting,and counting by use the uthash.
#include<stdio.h>
#include"uthash.h"
#include<stdlib.h>
#include"use_hash.h"


void print_hash(record_t *p)
{
        printf("success in hash_add and the p si:\n");
        printf("%d\n",p->key.saddr);
        printf("%d\n",p->key.daddr);
        printf("current source_port : %d\n",ntohs(p->key.source_port));
        printf("%d\n",ntohs(p->key.dest_port));
        printf("%d\n",p->key.protocol);
}

//this function is for the condition that the packet between the same host and same port
record_key_t * reverse_ip(record_key_t *p)
{
        record_key_t *temp;
        
        temp=(record_key_t*)malloc(sizeof(record_key_t));

        temp->saddr=p->daddr;
        temp->daddr=p->saddr;
        temp->source_port=p->dest_port;
        temp->dest_port=p->source_port;
        temp->protocol=p->protocol;

        return temp;
}

//this function is for the similar packet to store in the linked list that take the hash node as the head

void add_hash_collision(record_t *linked_head,record_t * p)
{
	record_t *temp;
	temp=linked_head;

	while(temp->next!=NULL)
	{
		temp=temp->next;
	}

	temp->next=p;
	printf("this record has be in a linked list\n");

	printf("and the number is   :%d\n",count_linked_head(linked_head));
	p->next=NULL;
}

//is to add key into a hash table;
void add_hash(record_t **head,record_t *p)
{
	record_t *temp;

	HASH_FIND(hh,*head,p,sizeof(record_key_t),temp);

	if(temp!=NULL)
	{
		add_hash_collision(temp,p);
		return;
	}
	
	HASH_ADD(hh,*head,key,sizeof(record_key_t),p);

	print_hash(p);
}	

//is to find a specific packet by key and reverse key
record_t * find_hash(record_t * head,record_key_t *p)
{
	record_t *temp;
	HASH_FIND(hh,head,p,sizeof(record_key_t),temp);
	
	record_t *temp_reverse;

	HASH_FIND(hh,head,reverse_ip(p),sizeof(record_key_t),temp_reverse);

	if(temp==NULL)
	{
		return temp_reverse;
	}

	return temp;
}

//is to delete a specific packet by key
void delete_hash(record_t **head,record_key_t *p)
{
	record_t *temp;
	temp=find_hash(*head,p);

	HASH_DEL(*head,temp);

	free(temp);
}

//is for count hash size
int count_hash(record_t *head)
{
	int num=0;
	num=HASH_COUNT(head);
	return num;
}


//this function is for a linked list in the case of collision to count the number follow by a linked head that is the node of hash

int count_linked_head(record_t * head)
{
	int num=0;
	record_t * temp=head;

	while(temp!=NULL)
	{
		num++;
		temp=temp->next;
	}
	
	return num;
}

